/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package moonnms.libs;

import java.io.IOException;
import java.util.HashMap;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;

/**
 *
 * @author Di_Moon
 */
public class libNMSSNMPClient {
    private String ipAddr;
    private String community;
    private TransportMapping transport;
    private CommunityTarget comtarget;
    private Snmp snmp;
    
    public libNMSSNMPClient(String addr, String comm) {
        ipAddr = addr;
        community = comm;
        
        try {
            transport = new DefaultUdpTransportMapping();
            transport.listen();
            
            comtarget = new CommunityTarget();
            comtarget.setCommunity(new OctetString(community));
            comtarget.setVersion(SnmpConstants.version2c);
            comtarget.setAddress(new UdpAddress(ipAddr+"/161"));
            comtarget.setRetries(2);
            comtarget.setTimeout(100);
            
            snmp = new Snmp(transport);            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public String getString(String oid) {
        
        PDU pdu = new PDU();
        pdu.add(new VariableBinding(new OID(oid)));
        pdu.setType(PDU.GET);
        pdu.setRequestID(new Integer32(1));
        
//        System.out.println("snmp Send request...");
        try {
            ResponseEvent response = snmp.get(pdu, comtarget);
            
            if(response != null) {
//                System.out.println("Got response!...");
                PDU responsePDU = response.getResponse();
                
                if(responsePDU != null) {
                    int errorStatus = responsePDU.getErrorStatus();
                    int errorIndex = responsePDU.getErrorIndex();
                    String errorStatusText = responsePDU.getErrorStatusText();
                    
                    if(errorStatus == PDU.noError) {
                        String result = responsePDU.getVariableBindings().firstElement().toValueString();
                        return result;
                    } else {
                        System.out.println("Error Index is "+errorIndex+". Status text is: "+errorStatusText);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        
        return null;
    }
    
    public int getInt(String oid) {
        return Integer.parseInt(getString(oid));
    }
    
    public long getLong(String oid) {
        return Long.parseLong(getString(oid));
    }
    
    public HashMap<String, String> walk(String strOID) {
        int iterator = 0;
        PDU requestPDU = new PDU();
        OID oid = new OID(strOID);
        requestPDU.add(new VariableBinding(oid));
        requestPDU.setType(PDU.GETBULK);
        requestPDU.setMaxRepetitions(1);
        
        HashMap<String, String> ret = new HashMap<String, String>();
        
        try {
            boolean finished = false;
            while(!finished) {
                VariableBinding vb = null;
                
                ResponseEvent responseEvt = snmp.send(requestPDU, comtarget);
                iterator++;
//                System.out.println("Iterator "+iterator);
                PDU responsePDU = responseEvt.getResponse();
                
                if(responsePDU != null) {
                    vb = responsePDU.get(responsePDU.size()-1);
                }
                
                if(responsePDU == null) {
                    finished = true;
                } else if (responsePDU.getErrorStatus() != 0) {
                    finished = true;
                } else if (vb.getOid() == null) {
                    finished = true;
                } else if (vb.getOid().size() < oid.size()) {
                    finished = true;
                } else if (oid.leftMostCompare(oid.size(), vb.getOid()) != 0) {
                    finished = true;
                } else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())) {
                    finished = true;
                } else if (vb.getOid().compareTo(oid) <= 0) {
                    finished = true;
                } else {
                    Vector<? extends VariableBinding> vbs = responsePDU.getVariableBindings();
                    
                    if(vbs!=null && vbs.size() > 0) {
                        for(int i=0; i < vbs.size(); i++) {
                            String rOid = vbs.get(i).getOid().toString();
                            String rValue = vbs.get(i).toValueString();
                            
                            ret.put(rOid, rValue);
//                            System.out.println(rOid+" = "+rValue);
//                            System.out.println(vbs.get(i).toString());
                        }
                    }
                }
                
                requestPDU.setRequestID(new Integer32(0));
                requestPDU.set(0, vb);
            }
            return ret;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public void disconnect() {
        try {
            snmp.close();
        } catch (IOException ex) {
            Logger.getLogger(libNMSSNMPClient.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void setInt(String oid, int value) {
        VariableBinding vb = new VariableBinding(new OID(oid));
        vb.setVariable(new Integer32(value));

        PDU pdu = new PDU();
        pdu.add(vb);
        pdu.setType(PDU.SET);
        pdu.setRequestID(new Integer32(1));
     
        try {
            ResponseEvent response;
            response = snmp.set(pdu, comtarget);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void setString(String oid, String value) {
        VariableBinding vb = new VariableBinding(new OID(oid));
        vb.setVariable(new OctetString(value));

        PDU pdu = new PDU();
        pdu.add(vb);
        pdu.setType(PDU.SET);
        pdu.setRequestID(new Integer32(1));
     
        try {
            ResponseEvent response;
            response = snmp.set(pdu, comtarget);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void setHex(String oid, String value) {
        VariableBinding vb = new VariableBinding(new OID(oid));
        vb.setVariable(OctetString.fromHexString(value));

        PDU pdu = new PDU();
        pdu.add(vb);
        pdu.setType(PDU.SET);
        pdu.setRequestID(new Integer32(1));
     
        try {
            ResponseEvent response;
            response = snmp.set(pdu, comtarget);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}
